from numpy import *
import matplotlib.pyplot as plt
import time

def loadData():#训练样本,第一个1为阈值对应的w_0
    # 每一列是一个样本
    samples=[[1, 1, 1],
             [3, 4, 1],
             [3, 3, 1]]
    labels=[1, 1, -1]
    return samples, labels

class Perceptron:
    def __init__(self, x, y, eta=1):
        self.x = array(x)
        self.y = y
        self.eta = eta  # 学习率

        self.numFeatures = self.x.shape[0] # 行数
        self.numSamples = self.x.shape[1] # 列数
        self.w = zeros((self.numFeatures,1))  # 初始化权重，w0,w1,w2均为0
        
    def getSign(self, w, x):
        w = w.reshape(x.shape)
        y = dot(w, x)
        return sign(y)

    def update(self, label_i, data_i):
        tmp = self.eta * label_i * data_i
        tmp = tmp.reshape(self.w.shape)
        # 更新
        self.w = tmp + self.w

    def train(self):
        isFound = False
        num = 0
        while not isFound:
            count = 0
            for i in range(self.numSamples):
                tmpY = self.getSign(self.w, self.x[:, i])
                if tmpY * self.y[i] <= 0:  # 如果是一个误分类实例点
                    print('第',num,'次迭代误分类点为：', self.x[:, i], '此时的w为：', transpose(self.w))
                    count += 1
                    num += 1
                    self.update(self.y[i], self.x[:, i])
            if count == 0:
                print( '最终训练得到的w为：', transpose(self.w))
                isFound = True
        return self.w

def plotBestFit(samples, labels, w):
    xArr = array(samples)
    n = xArr.shape[1] # number of samples
    xcord1=[];ycord1=[]
    xcord2=[];ycord2=[]
    for i in range(n):
        if int(labels[i])==1:
            xcord1.append(xArr[1,i])
            ycord1.append(xArr[2,i])
        else:
            xcord2.append(xArr[1,i])
            ycord2.append(xArr[2,i])
    fig=plt.figure()
    ax= fig.add_subplot(111)
    ax.scatter(xcord1, ycord1,s=30,c='red',marker='s')  # 绘制散点图 标记点是方形
    ax.scatter(xcord2, ycord2,s=30,c='green')           # 绘制散点图 标记点是圆圈
    x = arange(-3.0, 3.0, 0.1)
    w = array(w)
    y = (-w[0]-w[1] * x)/w[2]  # 公式来源：分类直线(x2即y) w0 + w1*x1 + w2*x2 = 0 变换后即 y = (-w[0]-w[1] * x)/w[2]
    ax.plot(x, y)
    plt.xlabel('X1'); plt.ylabel('X2')
    plt.show()

if __name__=='__main__':
    start = time.time()
    samples, labels = loadData()
    myperceptron = Perceptron(x=samples, y=labels)
    weights = myperceptron.train()
    plotBestFit(samples, labels, weights)
    costtime = time.time() - start
    print("Time used:", costtime)